#ifndef LEX_H
#define LEX_H
#include "symbol.h"
#include <stdarg.h>
#define MAXKEY 1024 // 哈希表容量
#define CLR_GREY "\033[30m"
#define CLR_RED "\033[31m"
#define CLR_GREEN "\033[32m"
#define CLR_YELLOW "\033[33m"
#define CLR_BLUE "\033[34m"
#define CLR_PURPLE "\033[35m"
#define CLR_WHITE "\033[37m"

enum token_identifier
{
    /*运算符及分割符*/
    TK_PLUS,      //+
    TK_MINUS,     // -
    TK_STAR,      //*
    TK_DIVIDE,    // /
    TK_MOD,       // %
    TK_EQ,        // ==
    TK_NEQ,       // !=
    TK_LT,        //<
    TK_LEQ,       // <=
    Tk_GT,        // >
    TK_GEQ,       // >=
    TK_ASSIGN,    // =
    TK_POINTSTO,  // ->
    TK_DOT,       // .
    TK_AND,       // &
    TK_OPENPA,    // (
    TK_CLOSEPA,   // )
    TK_OPENBR,    // [
    TK_CLOSEBR,   // ]
    TK_BEGIN,     // {
    TK_END,       // }
    TK_SEMICOLON, // ;
    TK_COMMA,     // ,
    TK_ELLIPSIS,  // ...
    TK_EOF,       // 文件结束符

    /*  常量*/
    TK_CINT,
    TK_CCHAR,
    TK_CSTR,

    /*关键字*/
    KW_CHAR,     // char
    KW_SHORT,    // short
    KW_INT,      // int
    KW_VOID,     // void
    KW_STRUCT,   // struct
    KW_IF,       // if
    KW_ELSE,     // else
    KW_FOR,      // for
    KW_CONTINUE, // continue
    KW_BREAK,    // break
    KW_RETURN,   // return
    KW_SIZEOF,   // sizeof
    KW_ALIGN,    // __align
    KW_CDECL,    // __cdecl
    KW_STDCALL,  // __stdcall

    /*标志符*/
    TK_IDENT

};

typedef struct DynString
{
    int count;    // 字符串长度
    int capacity; // 包含该字符串的缓冲区长度
    char *data;   // 指向字符串的指针
} DynString;

typedef struct DynArray
{
    int count;    // 动态数组元素个数
    int capacity; // 动态数组缓冲区长度
    void **data;  // 指向数组指针数组
} DynArray;

typedef struct TkWord
{
    int tkcode;
    struct TkWord *next;
    char *spelling;
    struct Symbol *sym_struct;     // 结构体
    struct Symbol *sym_identifier; // 标志符
} TkWord;

/*错误级别*/
enum e_ErrorLevel
{
    LEVEL_WARNING, // 警告
    LEVEL_ERROR    // 错误
};

/*工作阶段*/
enum e_WorkStage
{
    STAGE_COMPILE, // 编译阶段
    STAGE_LINK     // 链接阶段
};

/*
词法状态枚举定义
*/
enum e_LexState
{
    LEX_NORMAL,
    LEX_SEP
};

void init(void);
void getch(void);
void get_token(void);
void color_token(int lex_state);
void cleanup(void);
void dynstring_init(DynString *pstr, int initsize);
void dynstring_free(DynString *pstr);
void dynstring_reset(DynString *pstr);
void dynstring_realloc(DynString *pstr, int new_size);
void dynstring_chcat(DynString *pstr, char ch);
void dynarray_realloc(DynArray *parr, int new_size);
void dynarray_add(DynArray *parr, void *data);
void dynarray_init(DynArray *parr, int initsize);
void dynarray_free(DynArray *parr);
int dynarray_search(DynArray *parr, int key);
int elf_hash(char *key);
TkWord *tkword_direct_insert(TkWord *tp);
TkWord *tkword_find(char *p, int keyno);
void *mallocz(int size);
TkWord *tkword_insert(char *p);
void init_lex(void);
void handle_except(int stage, int level, char *fmt, va_list ap);
void warning(char *fmt, ...);
void errorMsg(char *fmt, ...);
void except(char *msg);
char *get_tkstr(int v);

#endif
